昨天講了一個比較複雜的操作,今天我們來做一點點輕鬆的,順便當作複習前面的,今天要的是把分類相關的功能實作完成吧。
首先是序列化讓我們編輯 server/app/todo/serializers.py
檔案
# ...... 以上省略 ......
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = todo_models.Tag
fields = "__all__"
+class CategorySerializer(serializers.ModelSerializer):
+ class Meta:
+ model = todo_models.Category
+ fields = "__all__"
class TaskSerializer(serializers.ModelSerializer):
# ...... 以下省略 ......
這邊是建立了一個 CategorySerializer 序列化,接受所有 Category 的欄位傳入跟傳出。
接下來是 ViewSet 讓我們編輯 server/app/todo/views.py
檔案(將下面那段貼在檔案最下面)
class CategoryViewSet(viewsets.ModelViewSet):
queryset = todo_models.Category.objects.order_by("id")
serializer_class = todo_serializers.CategorySerializer
ordering_fields = ("id", "name")
search_fields = ("name",)
filterset_fields = {
"name": ("exact", "contains", "icontains"),
}
這邊是建立了一個 CategoryViewSet 資料的範圍是全部的分類(依 ID 排序)並使用 CategorySerializer 作為格式同時設定排序、搜尋與篩選的功能。
接下來是路由相關的設定讓我們編輯 server/urls.py
檔案
# ...... 以上省略 ......
router = routers.SimpleRouter(trailing_slash=False)
router.register("todo/tasks", todo_views.TaskViewSet)
router.register("todo/tags", todo_views.TagViewSet)
+router.register("todo/categories", todo_views.CategoryViewSet)
urlpatterns = [
# ...... 以下省略 ......
現在我們已將 CategoryViewSet 註冊進去了,現在大家可以試試看現在分類相關的增刪改查的功能都已經完成了~大家可以利用 Postman 試試看
P.S. 大家可能會發現這邊我路由用的是 categories
而不是 category
是因為 RESTful 的路由習慣用複數當作路徑名稱,所以這邊的 url 會是 http://127.0.0.1:8000/api/todo/categories。
接下來是 Admin 部分讓我們編輯 server/app/todo/admin.py
檔案
from django.contrib import admin
from server.app.todo import models as todo_models
@admin.register(todo_models.Task)
class TaskAdmin(admin.ModelAdmin):
list_display = ("title", "is_finish")
- list_filter = ("is_finish", "tags")
+ list_filter = ("is_finish", "tags", "category")
search_fields = ("title", "description")
filter_horizontal = ("tags",)
@admin.register(todo_models.Tag)
class TagAdmin(admin.ModelAdmin):
pass
+
+@admin.register(todo_models.Category)
+class CategoryAdmin(admin.ModelAdmin):
+ pass
我們在這邊新增 CategoryAdmin 讓 Category 可以在 Admin 系統編輯相關資料
跟之前的 Tag 的時候一樣我們需要讓我們呼叫 Task 列表 API 的時候可以拿到分類的的名稱,這樣就不用呼叫多次 API 來得到對的資料了
# ...... 以上省略 ......
class TaskSerializer(serializers.ModelSerializer):
tags = TagSerializer(many=True, read_only=True)
tag_ids = serializers.PrimaryKeyRelatedField(
allow_empty=False,
write_only=True,
many=True,
queryset=todo_models.Tag.objects.all(),
source="tags",
)
+ category = CategorySerializer(read_only=True)
+ category_id = serializers.PrimaryKeyRelatedField(
+ write_only=True,
+ queryset=todo_models.Category.objects.all(),
+ source="category",
+ )
+
class Meta:
model = todo_models.Task
fields = "__all__"
# ...... 以下省略
現在這樣我們建立 Task 時就可以利用 category_id 指定關聯的分類,並從 category 欄位得到分類的完整資訊(包含 ID 與 name)
今天做的東西都比較簡單,算是複習前面的內容,但還是需要做,因為後面的範例會使用到~
結束前別忘了檢查一下今天的程式碼有沒有問題,並排版好喔。
ruff check --fix .
black .
pyright .
今天的內容就到這邊了,讓我們期待明天的內容吧。
P.S. 今天的檔案更新可以參考我的 Git Commit 大家可以搭配服用